{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<table style=\"float:left; border:none\">\n",
    "   <tr style=\"border:none; background-color: #ffffff\">\n",
    "       <td style=\"border:none\">\n",
    "           <a href=\"http://bokeh.pydata.org/\">     \n",
    "           <img \n",
    "               src=\"assets/bokeh-transparent.png\" \n",
    "               style=\"width:50px\"\n",
    "           >\n",
    "           </a>    \n",
    "       </td>\n",
    "       <td style=\"border:none\">\n",
    "           <h1>Bokeh 教程</h1>\n",
    "       </td>\n",
    "   </tr>\n",
    "</table>\n",
    "\n",
    "<div style=\"float:right;\"><h2>A1. 模型和原语</h2></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 概述\n",
    "\n",
    "虽然被叫做一个名字，但 Bokeh 却是由两个单独的库组成。\n",
    "\n",
    "第一个是JavaScript库，BokehJS，在浏览器中运行。这个库负责所有的呈现和用户交互。它的输入是一系列陈述性JSON对象组成的“场景图”。这个场景图中的对象描述了BokehJS要处理的一切：要呈现的plots和widgets，怎么排列，有什么工具、渲染器、轴，等等。这些JSON对象在浏览器中被转换成JavaScript对象。\n",
    "\n",
    "第二个是Python（或其他语言）写的用来生成上述JSON的一个库。Python Bokeh库中定义了一组底层 `Model` 子类，很好地镜像了浏览器中使用的BokehJS模型。大多数模型非常简单，通常由几个属性（attribute）组成，没有方法（method）。模型属性可以在创建模型时设置，也可以通过模型对象来设置其值：\n",
    "\n",
    "#### 属性可以在模型对象初始化的时候设置\n",
    "```python\n",
    "glyph = Rect(x=\"x\", y=\"y2\", w=10, h=20, line_color=None)\n",
    "```\n",
    "\n",
    "#### 属性可以通过赋值给模型对象的成员来设置\n",
    "```python\n",
    "glyph.fill_alpha = 0.5\n",
    "glyph.fill_color = \"navy\"\n",
    "```\n",
    "\n",
    "这些属性设置方法对所有Bokeh模型都适用。\n",
    "\n",
    "为了 bokehJS 和 Bokeh Python绑定之间的序列化，Bokeh模型最终被收集到 Bokeh `Document` 里。举个例子，下面的图片展示了一个简单图表的示例文档：\n",
    "\n",
    "![Document Structure](assets/document.svg)\n",
    "\n",
    "这样的文档可以使用高级的 `bokeh.plotting` API 创建，自动合理地组织适当的模型如轴线、网格和工具栏。也可以使用低级的 `bokeh.models` API “手动”组装所有的部件。使用 `bokeh.models` 接口提供了对Bokeh plots和widgets如何布置安排和配置的完全控制。然而，它不提供如何组装模型的帮助，完全由开发者“手动”建立场景。\n",
    "\n",
    "更多Bokeh模型的细节信息，请参考 [参考手册](http://bokeh.pydata.org/en/latest/docs/reference.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 示例演练\n",
    "\n",
    "让我们尝试使用 `bokeh.models` 接口重现这个纽约时报的交互式图表 [Usain Bolt vs. 116 years of Olympic sprinters](http://www.nytimes.com/interactive/2012/08/05/sports/olympics/the-100-meter-dash-one-race-every-medalist-ever.html)。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们需要做的第一件事就是获取数据。此图表的数据可在 ``bokeh.sampledata`` 模块中找到，作为一个Pandas DataFrame数据。您可以看看前十行数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Country</th>\n",
       "      <th>Medal</th>\n",
       "      <th>Time</th>\n",
       "      <th>Year</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Usain Bolt</td>\n",
       "      <td>JAM</td>\n",
       "      <td>GOLD</td>\n",
       "      <td>9.63</td>\n",
       "      <td>2012</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Yohan Blake</td>\n",
       "      <td>JAM</td>\n",
       "      <td>SILVER</td>\n",
       "      <td>9.75</td>\n",
       "      <td>2012</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Justin Gatlin</td>\n",
       "      <td>USA</td>\n",
       "      <td>BRONZE</td>\n",
       "      <td>9.79</td>\n",
       "      <td>2012</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Usain Bolt</td>\n",
       "      <td>JAM</td>\n",
       "      <td>GOLD</td>\n",
       "      <td>9.69</td>\n",
       "      <td>2008</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Richard Thompson</td>\n",
       "      <td>TRI</td>\n",
       "      <td>SILVER</td>\n",
       "      <td>9.89</td>\n",
       "      <td>2008</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Walter Dix</td>\n",
       "      <td>USA</td>\n",
       "      <td>BRONZE</td>\n",
       "      <td>9.91</td>\n",
       "      <td>2008</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Justin Gatlin</td>\n",
       "      <td>USA</td>\n",
       "      <td>GOLD</td>\n",
       "      <td>9.85</td>\n",
       "      <td>2004</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Francis Obikwelu</td>\n",
       "      <td>POR</td>\n",
       "      <td>SILVER</td>\n",
       "      <td>9.86</td>\n",
       "      <td>2004</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Maurice Greene</td>\n",
       "      <td>USA</td>\n",
       "      <td>BRONZE</td>\n",
       "      <td>9.87</td>\n",
       "      <td>2004</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Maurice Greene</td>\n",
       "      <td>USA</td>\n",
       "      <td>GOLD</td>\n",
       "      <td>9.87</td>\n",
       "      <td>2000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Name Country   Medal  Time  Year\n",
       "0        Usain Bolt     JAM    GOLD  9.63  2012\n",
       "1       Yohan Blake     JAM  SILVER  9.75  2012\n",
       "2     Justin Gatlin     USA  BRONZE  9.79  2012\n",
       "3        Usain Bolt     JAM    GOLD  9.69  2008\n",
       "4  Richard Thompson     TRI  SILVER  9.89  2008\n",
       "5        Walter Dix     USA  BRONZE  9.91  2008\n",
       "6     Justin Gatlin     USA    GOLD  9.85  2004\n",
       "7  Francis Obikwelu     POR  SILVER  9.86  2004\n",
       "8    Maurice Greene     USA  BRONZE  9.87  2004\n",
       "9    Maurice Greene     USA    GOLD  9.87  2000"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from bokeh.sampledata.sprint import sprint\n",
    "sprint[:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下一步，我们导入一些组合图表所需的Bokeh模型。不用太多，我们从 ``Plot`` 开始，还有要显示的标记符（``Circle`` 和 ``Text``），以及保存数据的 ``ColumnDataSource`` 和设置图表界限的 range 对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.io import output_notebook, show\n",
    "from bokeh.models.glyphs import Circle, Text\n",
    "from bokeh.models import ColumnDataSource, Range1d, DataRange1d, Plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id !== undefined) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var element_id = msg.content.text.trim();\n",
       "            Bokeh.index[element_id].model.document.clear();\n",
       "            delete Bokeh.index[element_id];\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[0].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[0].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[0]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };var element = document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\");\n",
       "  if (element == null) {\n",
       "    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.12.13.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };var element = document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\");\n  if (element == null) {\n    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb' but no matching script tag was found. \")\n    return false;\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-0.12.13.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.13.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-0.12.13.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"3f3f70c7-2adf-4d98-a6b6-f5feb99f41cb\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "output_notebook()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setting up Data\n",
    "\n",
    "接下来，我们需要在列数据源中设置我们所有想要的列。在这里，我们添加一些额外的列如 `MetersBack` 和 `SelectedName`（后面我们做 `HoverTool` 的时候会用到）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "abbrev_to_country = {\n",
    "    \"USA\": \"United States\",\n",
    "    \"GBR\": \"Britain\",\n",
    "    \"JAM\": \"Jamaica\",\n",
    "    \"CAN\": \"Canada\",\n",
    "    \"TRI\": \"Trinidad and Tobago\",\n",
    "    \"AUS\": \"Australia\",\n",
    "    \"GER\": \"Germany\",\n",
    "    \"CUB\": \"Cuba\",\n",
    "    \"NAM\": \"Namibia\",\n",
    "    \"URS\": \"Soviet Union\",\n",
    "    \"BAR\": \"Barbados\",\n",
    "    \"BUL\": \"Bulgaria\",\n",
    "    \"HUN\": \"Hungary\",\n",
    "    \"NED\": \"Netherlands\",\n",
    "    \"NZL\": \"New Zealand\",\n",
    "    \"PAN\": \"Panama\",\n",
    "    \"POR\": \"Portugal\",\n",
    "    \"RSA\": \"South Africa\",\n",
    "    \"EUA\": \"United Team of Germany\",\n",
    "}\n",
    "\n",
    "fill_color = { \"gold\": \"#efcf6d\", \"silver\": \"#cccccc\", \"bronze\": \"#c59e8a\" }\n",
    "line_color = { \"gold\": \"#c8a850\", \"silver\": \"#b0b0b1\", \"bronze\": \"#98715d\" }\n",
    "\n",
    "def selected_name(name, medal, year):\n",
    "    return name if medal == \"gold\" and year in [1988, 1968, 1936, 1896] else \"\"\n",
    "\n",
    "t0 = sprint.Time[0]\n",
    "\n",
    "sprint[\"Abbrev\"]       = sprint.Country\n",
    "sprint[\"Country\"]      = sprint.Abbrev.map(lambda abbr: abbrev_to_country[abbr])\n",
    "sprint[\"Medal\"]        = sprint.Medal.map(lambda medal: medal.lower())\n",
    "sprint[\"Speed\"]        = 100.0/sprint.Time\n",
    "sprint[\"MetersBack\"]   = 100.0*(1.0 - t0/sprint.Time)\n",
    "sprint[\"MedalFill\"]    = sprint.Medal.map(lambda medal: fill_color[medal])\n",
    "sprint[\"MedalLine\"]    = sprint.Medal.map(lambda medal: line_color[medal])\n",
    "sprint[\"SelectedName\"] = sprint[[\"Name\", \"Medal\", \"Year\"]].apply(tuple, axis=1).map(lambda args: selected_name(*args))\n",
    "\n",
    "source = ColumnDataSource(sprint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 逐步修建图表\n",
    "\n",
    "让我们逐步修建我们的图表，时不时停下来检查下输出，看看修得怎么样了。\n",
    "Let's build up our plot in stages, stopping to check the output along the way to see how things look.\n",
    "\n",
    "当我们开始时，请注意 `Plot`, `Chart`, 和 `Figure`都有的三个调用：\n",
    "\n",
    "* `p.add_glyph`\n",
    "* `p.add_tools`\n",
    "* `p.add_layout`\n",
    "\n",
    "这些便利调用方法帮助我们以正确的方式添加模型到 `Plot` 对象中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 只有标记符的基本图表\n",
    "\n",
    "首先，我们创建一个只有标题和一些基本样式的 `Plot`，并为实际的比赛数据添加一些 `Circle` 标记符。为了手动配置标记符，我们首先创建一个glyph对象（例如，`Text`或`Circle`），设置我们想要的视觉样式以及坐标数据。然后，我们调用 `plot.add_glyph` 添加标记符和相应的数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_options = dict(plot_width=800, plot_height=480, toolbar_location=None, outline_line_color=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "medal_glyph = Circle(x=\"MetersBack\", y=\"Year\", size=10, fill_color=\"MedalFill\", \n",
    "                     line_color=\"MedalLine\", fill_alpha=0.5)\n",
    "\n",
    "athlete_glyph = Text(x=\"MetersBack\", y=\"Year\", x_offset=10, text=\"SelectedName\",\n",
    "                     text_align=\"left\", text_baseline=\"middle\", text_font_size=\"9pt\")\n",
    "\n",
    "no_olympics_glyph = Text(x=7.5, y=1942, text=[\"No Olympics in 1940 or 1944\"],\n",
    "                         text_align=\"center\", text_baseline=\"middle\",\n",
    "                         text_font_size=\"9pt\", text_font_style=\"italic\", text_color=\"silver\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"display: table;\"><div style=\"display: table-row;\"><div style=\"display: table-cell;\"><b title=\"bokeh.models.renderers.GlyphRenderer\">GlyphRenderer</b>(</div><div style=\"display: table-cell;\">id&nbsp;=&nbsp;'9539a4a4-b166-4428-85da-4ec4d8ec9525', <span id=\"8c4d6956-968b-4edc-9081-3cbe178ca685\" style=\"cursor: pointer;\">&hellip;)</span></div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">data_source&nbsp;=&nbsp;ColumnDataSource(id='7734a8ee-a914-4c0a-81e1-08197617f719', ...),</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">glyph&nbsp;=&nbsp;Text(id='6547a6bb-c1e4-4278-b2c3-c0e2228a0d97', ...),</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">hover_glyph&nbsp;=&nbsp;None,</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_event_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_property_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">level&nbsp;=&nbsp;'glyph',</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted&nbsp;=&nbsp;False,</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted_glyph&nbsp;=&nbsp;None,</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">name&nbsp;=&nbsp;None,</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">nonselection_glyph&nbsp;=&nbsp;'auto',</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">selection_glyph&nbsp;=&nbsp;'auto',</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">subscribed_events&nbsp;=&nbsp;[],</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags&nbsp;=&nbsp;[],</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">view&nbsp;=&nbsp;CDSView(id='d2fc21cc-c42f-432c-b7a5-9ff315e99fb4', ...),</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">visible&nbsp;=&nbsp;True,</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_range_name&nbsp;=&nbsp;'default',</div></div><div class=\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_range_name&nbsp;=&nbsp;'default')</div></div></div>\n",
       "<script>\n",
       "(function() {\n",
       "  var expanded = false;\n",
       "  var ellipsis = document.getElementById(\"8c4d6956-968b-4edc-9081-3cbe178ca685\");\n",
       "  ellipsis.addEventListener(\"click\", function() {\n",
       "    var rows = document.getElementsByClassName(\"7ce924bc-d0d7-439b-a2f9-ea2017a9f5e8\");\n",
       "    for (var i = 0; i < rows.length; i++) {\n",
       "      var el = rows[i];\n",
       "      el.style.display = expanded ? \"none\" : \"table-row\";\n",
       "    }\n",
       "    ellipsis.innerHTML = expanded ? \"&hellip;)\" : \"&lsaquo;&lsaquo;&lsaquo;\";\n",
       "    expanded = !expanded;\n",
       "  });\n",
       "})();\n",
       "</script>\n"
      ],
      "text/plain": [
       "GlyphRenderer(id='9539a4a4-b166-4428-85da-4ec4d8ec9525', ...)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xdr = Range1d(start=sprint.MetersBack.max()+2, end=0)  # +2 is for padding\n",
    "ydr = DataRange1d(range_padding=0.05)  \n",
    "\n",
    "plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
    "plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
    "plot.add_glyph(source, medal_glyph)\n",
    "plot.add_glyph(source, athlete_glyph)\n",
    "plot.add_glyph(no_olympics_glyph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div class=\"bk-root\">\n",
       "    <div class=\"bk-plotdiv\" id=\"16ac781e-5264-44a8-82cc-0f21da17bc76\"></div>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"c7be1f21-b8d8-4f41-a2b5-0f8e8bf3f805\":{\"roots\":{\"references\":[{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"bb8062e7-bdc8-40ae-bb70-94763f29621e\",\"type\":\"CDSView\"},{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"7f32bc9e-e478-43ad-957b-a65fcec94fab\",\"type\":\"CDSView\"},{\"attributes\":{\"outline_line_color\":{\"value\":null},\"plot_height\":480,\"plot_width\":800,\"renderers\":[{\"id\":\"6756aa44-7da1-4bfa-9d62-83e277494b6d\",\"type\":\"GlyphRenderer\"},{\"id\":\"430b9dd6-6a35-4629-b2bd-3887e3a0d9c5\",\"type\":\"GlyphRenderer\"},{\"id\":\"9539a4a4-b166-4428-85da-4ec4d8ec9525\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"8188d61a-880e-4221-84a9-c301d69389d8\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"f70c4198-75c1-4318-981e-97ebdbb09b73\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"b3307392-fbe2-44da-90fd-aa5663962da3\",\"type\":\"Range1d\"},\"x_scale\":{\"id\":\"c53c26e4-f91a-4ac9-96c6-05d7e1488699\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1993e924-d7e7-4d3b-b41f-fbf71077d8c1\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"374edbe9-974b-4e7c-b81c-52bb060bd103\",\"type\":\"LinearScale\"}},\"id\":\"f980bd49-870e-4253-94ee-7eaca1f58801\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"374edbe9-974b-4e7c-b81c-52bb060bd103\",\"type\":\"LinearScale\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_scroll\":\"auto\",\"active_tap\":\"auto\"},\"id\":\"f70c4198-75c1-4318-981e-97ebdbb09b73\",\"type\":\"Toolbar\"},{\"attributes\":{\"data_source\":{\"id\":\"7734a8ee-a914-4c0a-81e1-08197617f719\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"d2fc21cc-c42f-432c-b7a5-9ff315e99fb4\",\"type\":\"CDSView\"}},\"id\":\"9539a4a4-b166-4428-85da-4ec4d8ec9525\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"c53c26e4-f91a-4ac9-96c6-05d7e1488699\",\"type\":\"LinearScale\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"bb8062e7-bdc8-40ae-bb70-94763f29621e\",\"type\":\"CDSView\"}},\"id\":\"6756aa44-7da1-4bfa-9d62-83e277494b6d\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null,\"end\":0,\"start\":25.571428571428566},\"id\":\"b3307392-fbe2-44da-90fd-aa5663962da3\",\"type\":\"Range1d\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"7f32bc9e-e478-43ad-957b-a65fcec94fab\",\"type\":\"CDSView\"}},\"id\":\"430b9dd6-6a35-4629-b2bd-3887e3a0d9c5\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"7734a8ee-a914-4c0a-81e1-08197617f719\",\"type\":\"ColumnDataSource\"}},\"id\":\"d2fc21cc-c42f-432c-b7a5-9ff315e99fb4\",\"type\":\"CDSView\"},{\"attributes\":{\"text\":{\"field\":\"SelectedName\"},\"text_baseline\":\"middle\",\"text_font_size\":{\"value\":\"9pt\"},\"x\":{\"field\":\"MetersBack\"},\"x_offset\":{\"value\":10},\"y\":{\"field\":\"Year\"}},\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},{\"attributes\":{\"callback\":null,\"range_padding\":0.05},\"id\":\"1993e924-d7e7-4d3b-b41f-fbf71077d8c1\",\"type\":\"DataRange1d\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"field\":\"MedalFill\"},\"line_color\":{\"field\":\"MedalLine\"},\"size\":{\"units\":\"screen\",\"value\":10},\"x\":{\"field\":\"MetersBack\"},\"y\":{\"field\":\"Year\"}},\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},{\"attributes\":{\"callback\":null,\"data\":{}},\"id\":\"7734a8ee-a914-4c0a-81e1-08197617f719\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"text\":{\"value\":\"No Olympics in 1940 or 1944\"},\"text_align\":\"center\",\"text_baseline\":\"middle\",\"text_color\":{\"value\":\"silver\"},\"text_font_size\":{\"value\":\"9pt\"},\"text_font_style\":\"italic\",\"x\":{\"value\":7.5},\"y\":{\"value\":1942}},\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"MetersBack\",\"MedalLine\",\"SelectedName\",\"Name\",\"Country\",\"index\",\"Speed\",\"Medal\",\"Year\",\"MedalFill\",\"Time\",\"Abbrev\"],\"data\":{\"Abbrev\":[\"JAM\",\"JAM\",\"USA\",\"JAM\",\"TRI\",\"USA\",\"USA\",\"POR\",\"USA\",\"USA\",\"TRI\",\"BAR\",\"CAN\",\"NAM\",\"TRI\",\"GBR\",\"NAM\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"CAN\",\"GBR\",\"CUB\",\"BUL\",\"TRI\",\"JAM\",\"URS\",\"URS\",\"USA\",\"JAM\",\"USA\",\"JAM\",\"USA\",\"USA\",\"CUB\",\"CAN\",\"EUA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"AUS\",\"USA\",\"JAM\",\"GBR\",\"USA\",\"USA\",\"PAN\",\"USA\",\"USA\",\"NED\",\"USA\",\"USA\",\"GER\",\"CAN\",\"GBR\",\"GER\",\"GBR\",\"USA\",\"NZL\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"RSA\",\"USA\",\"CAN\",\"USA\",\"USA\",\"AUS\",\"USA\",\"USA\",\"USA\",\"USA\",\"USA\",\"AUS\",\"USA\",\"GER\",\"HUN\",\"USA\"],\"Country\":[\"Jamaica\",\"Jamaica\",\"United States\",\"Jamaica\",\"Trinidad and Tobago\",\"United States\",\"United States\",\"Portugal\",\"United States\",\"United States\",\"Trinidad and Tobago\",\"Barbados\",\"Canada\",\"Namibia\",\"Trinidad and Tobago\",\"Britain\",\"Namibia\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"Canada\",\"Britain\",\"Cuba\",\"Bulgaria\",\"Trinidad and Tobago\",\"Jamaica\",\"Soviet Union\",\"Soviet Union\",\"United States\",\"Jamaica\",\"United States\",\"Jamaica\",\"United States\",\"United States\",\"Cuba\",\"Canada\",\"United Team of Germany\",\"United States\",\"Britain\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Jamaica\",\"Britain\",\"United States\",\"United States\",\"Panama\",\"United States\",\"United States\",\"Netherlands\",\"United States\",\"United States\",\"Germany\",\"Canada\",\"Britain\",\"Germany\",\"Britain\",\"United States\",\"New Zealand\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"South Africa\",\"United States\",\"Canada\",\"United States\",\"United States\",\"Australia\",\"United States\",\"United States\",\"United States\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Germany\",\"Hungary\",\"United States\"],\"Medal\":[\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"bronze\"],\"MedalFill\":[\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#c59e8a\"],\"MedalLine\":[\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#98715d\"],\"MetersBack\":{\"__ndarray__\":\"AAAAAAAAAAD2OrETO7HzPzSH3n8tJvo/+LRJIXLQ4z+4oVs2BggFQE37LXJ6mgZApWIklDbeAUD2G7ItSKkCQBFzDHDwcwNAEXMMcPBzA0A7zUkgLtQMQMAp1V2sVRBA/rQrUbsSAUC4oVs2BggFQMdFF1100QVAuPaQy4qBCkC79onqQSMPQMAp1V2sVRBAV4wxxhhjB0A2Q3IHJ0gLQDvNSSAu1AxAO81JIC7UDEDqKu9YevsVQHzx4sWLFxdALDgfg/MxGEAsOB+D8zEYQO/PDHRHQh1AQ4IAOfAYEUCybdu2bdsRQGZfWb1LHhRAZl9ZvUseFED0/////9MXQEJPwDgDGxtAX4SfXIi6CUDAKdVdrFUQQFLnrrBHehFAiJmZmZmZDUBQWlpaWloWQFBaWlpaWhZAUFpaWlpaFkBQWlpaWloWQCQ5L4v4BBpAHkmSJEmSIEAeSZIkSZIgQN+t7HNITSJA1Imd2ImdHUDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQB5JkiRJkiBAJDkvi/gEGkAkOS+L+AQaQNSJndiJnR1AqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdA363sc0hNIkCoqqqqqqolQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDnoosuuugoQOeiiy666ChAiSRJkiQJLECa6xjFuY4tQJrrGMW5ji1A56KLLrroKECJJEmSJAksQIkkSZIkCSxA56KLLrroKEDBZ91ginwqQIkkSZIkCSxA/f////+/M0DYvE9xyRA1QCNJkiRJkjdAI0mSJEmSN0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Name\":[\"Usain Bolt\",\"Yohan Blake\",\"Justin Gatlin\",\"Usain Bolt\",\"Richard Thompson\",\"Walter Dix\",\"Justin Gatlin\",\"Francis Obikwelu\",\"Maurice Greene\",\"Maurice Greene\",\"Ato Boldon\",\"Obadele Thompson\",\"Donovan Bailey\",\"Frankie Fredericks\",\"Ato Boldon\",\"Linford Christie\",\"Frankie Fredericks\",\"Dennis Mitchell\",\"Carl Lewis\",\"Linford Christie\",\"Calvin Smith\",\"Carl Lewis\",\"Sam Graddy\",\"Ben Johnson\",\"Allan Wells\",\"Silvio Leonard Tartabull\",\"Petar Petrov\",\"Hasely Crawford\",\"Donald Quarrie\",\"Valery Borzov\",\"Valery Borzov\",\"Robert Taylor\",\"Lennox Miller\",\"Jim Hines\",\"Lennox Miller\",\"Charles Greene\",\"Bob Hayes\",\"Enrique Figuerola Camue\",\"Harry Jerome\",\"Armin Hary\",\"David Sime\",\"Peter Radford\",\"Bobby Joe Morrow\",\"W. Thane Baker\",\"Hector Hogan\",\"Lindy Remigino\",\"Herbert McKenley\",\"E. McDonald Bailey\",\"W. Harrison Dillard\",\"H. Norwood \\\"Barney\\\" Ewell\",\"Lloyd LaBeach\",\"Jesse Owens\",\"Ralph Metcalfe\",\"Martinus Osendarp\",\"T. \\\"Eddie\\\" Tolan\",\"Ralph Metcalfe\",\"Arthur Jonath\",\"Percy Williams\",\"John \\\"Jack\\\" London\",\"Georg Lammers\",\"Harold Abrahams\",\"Jackson Scholz\",\"Arthur Porritt\",\"Charles Paddock\",\"Morris Kirksey\",\"Harry Edward\",\"Ralph Craig\",\"Alvah Meyer\",\"Donald Lippincott\",\"Reginald Walker\",\"James Rector\",\"Robert Kerr\",\"Charles \\\"Archie\\\" Hahn\",\"Fay Moulton\",\"Nigel Barker\",\"Charles \\\"Archie\\\" Hahn\",\"Nathaniel Cartmell\",\"Bill Hogenson\",\"Frank Jarvis\",\"J. Walter Tewksbury\",\"Stanley Rowley\",\"Thomas Burke\",\"Fritz Hofmann\",\"Alojz Sokol\",\"Francis Lane\"],\"SelectedName\":[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Carl Lewis\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jim Hines\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jesse Owens\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Thomas Burke\",\"\",\"\",\"\"],\"Speed\":{\"__ndarray__\":\"D9dd9bfEJEA1SIM0SIMkQNPZ5YvTbSRAEB0COMyjJEBnpfVH8jgkQGugzZx/LiRAUs36M/hNJEDfP/mgskgkQPb3DMpvQyRA9vcMym9DJEBSQDMIIAUkQP8yCgKa6yNAUwg0hUBTJEBnpfVH8jgkQN7OkJi3MyRA9dmM748UJEB3uNvKx/UjQP8yCgKa6yNAKaWUUkopJEBoIvL9Zw8kQFJAMwggBSRAUkAzCCAFJEDuitWqiKAjQBw5cuTIkSNAg/MxOB+DI0CD8zE4H4MjQLW+ZrHQPyNAA1ahlXbhI0B2Xdd1XdcjQKh2L0ZPuSNAqHYvRk+5I0AAAAAAAIgjQBMU9wNwXCNAhZ9ciLoZJED/MgoCmusjQFfYI71o3CNAAAAAAAAAJECcm5ubm5sjQJybm5ubmyNAnJubm5ubI0Ccm5ubm5sjQAxNd7DfaiNAwzAMwzAMI0DDMAzDMAwjQO1zSE0w3iJAsRM7sRM7I0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQMMwDMMwDCNADE13sN9qI0AMTXew32ojQLETO7ETOyNATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJA7XNITTDeIkBMaC+hvYQiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkAvuuiiiy4iQC+66KKLLiJAt23btm3bIUCTLxs0+bIhQJMvGzT5siFAL7rooosuIkC3bdu2bdshQLdt27Zt2yFAL7rooosuIkBKIC7UnAQiQLdt27Zt2yFAq6qqqqqqIEAebd6nuGQgQPD7vu/7vh9A8Pu+7/u+H0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Time\":{\"__ndarray__\":\"w/UoXI9CI0AAAAAAAIAjQBSuR+F6lCNA4XoUrkdhI0BI4XoUrscjQFK4HoXr0SNAMzMzMzOzI0C4HoXrUbgjQD0K16NwvSNAPQrXo3C9I0B7FK5H4fojQBSuR+F6FCRArkfhehSuI0BI4XoUrscjQM3MzMzMzCNA7FG4HoXrI0AK16NwPQokQBSuR+F6FCRA16NwPQrXI0BxPQrXo/AjQHsUrkfh+iNAexSuR+H6I0DhehSuR2EkQHE9CtejcCRAAAAAAACAJEAAAAAAAIAkQEjhehSuxyRAH4XrUbgeJEApXI/C9SgkQEjhehSuRyRASOF6FK5HJEB7FK5H4XokQClcj8L1qCRAZmZmZmbmI0AUrkfhehQkQKRwPQrXIyRAAAAAAAAAJEBmZmZmZmYkQGZmZmZmZiRAZmZmZmZmJEBmZmZmZmYkQJqZmZmZmSRAAAAAAAAAJUAAAAAAAAAlQDMzMzMzMyVAzczMzMzMJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQAAAAAAAACVAmpmZmZmZJECamZmZmZkkQM3MzMzMzCRAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAMzMzMzMzJUCamZmZmZklQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUAAAAAAAAAmQAAAAAAAACZAZmZmZmZmJkCamZmZmZkmQJqZmZmZmSZAAAAAAAAAJkBmZmZmZmYmQGZmZmZmZiZAAAAAAAAAJkAzMzMzMzMmQGZmZmZmZiZAAAAAAAAAKEBmZmZmZmYoQDMzMzMzMylAMzMzMzMzKUA=\",\"dtype\":\"float64\",\"shape\":[85]},\"Year\":[2012,2012,2012,2008,2008,2008,2004,2004,2004,2000,2000,2000,1996,1996,1996,1992,1992,1992,1988,1988,1988,1984,1984,1984,1980,1980,1980,1976,1976,1976,1972,1972,1972,1968,1968,1968,1964,1964,1964,1960,1960,1960,1956,1956,1956,1952,1952,1952,1948,1948,1948,1936,1936,1936,1932,1932,1932,1928,1928,1928,1924,1924,1924,1920,1920,1920,1912,1912,1912,1908,1908,1908,1906,1906,1906,1904,1904,1904,1900,1900,1900,1896,1896,1896,1896],\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84]}},\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"plot\":null,\"text\":\"Usain Bolt vs. 116 years of Olympic sprinters\"},\"id\":\"8188d61a-880e-4221-84a9-c301d69389d8\",\"type\":\"Title\"}],\"root_ids\":[\"f980bd49-870e-4253-94ee-7eaca1f58801\"]},\"title\":\"Bokeh Application\",\"version\":\"0.12.13\"}};\n",
       "  var render_items = [{\"docid\":\"c7be1f21-b8d8-4f41-a2b5-0f8e8bf3f805\",\"elementid\":\"16ac781e-5264-44a8-82cc-0f21da17bc76\",\"modelid\":\"f980bd49-870e-4253-94ee-7eaca1f58801\"}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "f980bd49-870e-4253-94ee-7eaca1f58801"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show(plot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 加入轴线和网格线\n",
    "\n",
    "接下来，我们添加我们想看到的 `Axis` 和 `Grids` 模型。因为我们想要对外观进行更多的控制，所以我们选择一个有特殊刻度的轴模型（这里选择`singleintervalticker`）。然后，我们使用 `plot.add_layout` 方法把它们添加到图表。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.models import Grid, LinearAxis, SingleIntervalTicker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"display: table;\"><div style=\"display: table-row;\"><div style=\"display: table-cell;\"><b title=\"bokeh.models.renderers.GlyphRenderer\">GlyphRenderer</b>(</div><div style=\"display: table-cell;\">id&nbsp;=&nbsp;'0fecf8b7-44e7-4c31-8477-a249cc03473b', <span id=\"043991d0-8501-4b45-adef-5d507cd17f23\" style=\"cursor: pointer;\">&hellip;)</span></div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">data_source&nbsp;=&nbsp;ColumnDataSource(id='6ae154ab-2dd9-467f-9405-40a7f5607f59', ...),</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">glyph&nbsp;=&nbsp;Text(id='6547a6bb-c1e4-4278-b2c3-c0e2228a0d97', ...),</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">hover_glyph&nbsp;=&nbsp;None,</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_event_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">js_property_callbacks&nbsp;=&nbsp;{},</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">level&nbsp;=&nbsp;'glyph',</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted&nbsp;=&nbsp;False,</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">muted_glyph&nbsp;=&nbsp;None,</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">name&nbsp;=&nbsp;None,</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">nonselection_glyph&nbsp;=&nbsp;'auto',</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">selection_glyph&nbsp;=&nbsp;'auto',</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">subscribed_events&nbsp;=&nbsp;[],</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">tags&nbsp;=&nbsp;[],</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">view&nbsp;=&nbsp;CDSView(id='cc91ab49-ad0c-4a60-b7f7-c028eb17209d', ...),</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">visible&nbsp;=&nbsp;True,</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">x_range_name&nbsp;=&nbsp;'default',</div></div><div class=\"8a0cf77d-949c-491e-90ad-8735780958ea\" style=\"display: none;\"><div style=\"display: table-cell;\"></div><div style=\"display: table-cell;\">y_range_name&nbsp;=&nbsp;'default')</div></div></div>\n",
       "<script>\n",
       "(function() {\n",
       "  var expanded = false;\n",
       "  var ellipsis = document.getElementById(\"043991d0-8501-4b45-adef-5d507cd17f23\");\n",
       "  ellipsis.addEventListener(\"click\", function() {\n",
       "    var rows = document.getElementsByClassName(\"8a0cf77d-949c-491e-90ad-8735780958ea\");\n",
       "    for (var i = 0; i < rows.length; i++) {\n",
       "      var el = rows[i];\n",
       "      el.style.display = expanded ? \"none\" : \"table-row\";\n",
       "    }\n",
       "    ellipsis.innerHTML = expanded ? \"&hellip;)\" : \"&lsaquo;&lsaquo;&lsaquo;\";\n",
       "    expanded = !expanded;\n",
       "  });\n",
       "})();\n",
       "</script>\n"
      ],
      "text/plain": [
       "GlyphRenderer(id='0fecf8b7-44e7-4c31-8477-a249cc03473b', ...)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xdr = Range1d(start=sprint.MetersBack.max()+2, end=0)  # +2 is for padding\n",
    "ydr = DataRange1d(range_padding=0.05)  \n",
    "\n",
    "plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
    "plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
    "plot.add_glyph(source, medal_glyph)\n",
    "plot.add_glyph(source, athlete_glyph)\n",
    "plot.add_glyph(no_olympics_glyph)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "xticker = SingleIntervalTicker(interval=5, num_minor_ticks=0)\n",
    "xaxis = LinearAxis(ticker=xticker, axis_line_color=None, major_tick_line_color=None,\n",
    "                   axis_label=\"Meters behind 2012 Bolt\", axis_label_text_font_size=\"10pt\", \n",
    "                   axis_label_text_font_style=\"bold\")\n",
    "plot.add_layout(xaxis, \"below\")\n",
    "\n",
    "xgrid = Grid(dimension=0, ticker=xaxis.ticker, grid_line_dash=\"dashed\")\n",
    "plot.add_layout(xgrid)\n",
    "\n",
    "yticker = SingleIntervalTicker(interval=12, num_minor_ticks=0)\n",
    "yaxis = LinearAxis(ticker=yticker, major_tick_in=-5, major_tick_out=10)\n",
    "plot.add_layout(yaxis, \"right\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div class=\"bk-root\">\n",
       "    <div class=\"bk-plotdiv\" id=\"61aebced-e287-4016-8297-ec274527af38\"></div>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"e45d1607-b9e0-4629-835b-d77cac56faa2\":{\"roots\":{\"references\":[{\"attributes\":{\"axis_label\":\"Meters behind 2012 Bolt\",\"axis_label_text_font_size\":{\"value\":\"10pt\"},\"axis_label_text_font_style\":\"bold\",\"axis_line_color\":{\"value\":null},\"formatter\":{\"id\":\"9d22b06e-837e-4b77-8632-cbe152700241\",\"type\":\"BasicTickFormatter\"},\"major_tick_line_color\":{\"value\":null},\"plot\":{\"id\":\"75f2e525-e634-424c-a4f5-17743e75dff9\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"6b04205a-4efc-4e91-a629-f05cdeb0ffc9\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"21a93351-bf20-4557-98ad-5ed957cbbffc\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"77e28dc9-a3c4-446c-88b2-52bde15e18ec\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"range_padding\":0.05},\"id\":\"8ed9971c-c51e-47f2-86d8-4e57158d1a20\",\"type\":\"DataRange1d\"},{\"attributes\":{\"below\":[{\"id\":\"21a93351-bf20-4557-98ad-5ed957cbbffc\",\"type\":\"LinearAxis\"}],\"outline_line_color\":{\"value\":null},\"plot_height\":480,\"plot_width\":800,\"renderers\":[{\"id\":\"7a6dfe4f-634e-4b6c-a3f5-bc4be0a7ecf6\",\"type\":\"GlyphRenderer\"},{\"id\":\"d8b62b87-35ab-4c2b-ad79-6fb9d98ff122\",\"type\":\"GlyphRenderer\"},{\"id\":\"0fecf8b7-44e7-4c31-8477-a249cc03473b\",\"type\":\"GlyphRenderer\"},{\"id\":\"21a93351-bf20-4557-98ad-5ed957cbbffc\",\"type\":\"LinearAxis\"},{\"id\":\"a05486f6-fa93-4eb1-b939-6544ba844214\",\"type\":\"Grid\"},{\"id\":\"c09e0c50-d57d-4b66-a6e5-f83d7cd58aba\",\"type\":\"LinearAxis\"}],\"right\":[{\"id\":\"c09e0c50-d57d-4b66-a6e5-f83d7cd58aba\",\"type\":\"LinearAxis\"}],\"title\":{\"id\":\"0f3893c1-a33c-4551-82b9-37733248052f\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"cd21fab5-c0b2-48ad-9e67-234e9f11352b\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"1a69424c-3345-4e00-90fa-7197a7ce98e1\",\"type\":\"Range1d\"},\"x_scale\":{\"id\":\"d96edf1a-1d7a-4474-841a-f69b7268f13d\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"8ed9971c-c51e-47f2-86d8-4e57158d1a20\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"77e28dc9-a3c4-446c-88b2-52bde15e18ec\",\"type\":\"LinearScale\"}},\"id\":\"75f2e525-e634-424c-a4f5-17743e75dff9\",\"type\":\"Plot\"},{\"attributes\":{\"source\":{\"id\":\"6ae154ab-2dd9-467f-9405-40a7f5607f59\",\"type\":\"ColumnDataSource\"}},\"id\":\"cc91ab49-ad0c-4a60-b7f7-c028eb17209d\",\"type\":\"CDSView\"},{\"attributes\":{\"plot\":null,\"text\":\"Usain Bolt vs. 116 years of Olympic sprinters\"},\"id\":\"0f3893c1-a33c-4551-82b9-37733248052f\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"7c26425d-c20f-4ead-baec-ec9df359f075\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"grid_line_dash\":[6],\"plot\":{\"id\":\"75f2e525-e634-424c-a4f5-17743e75dff9\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"6b04205a-4efc-4e91-a629-f05cdeb0ffc9\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"a05486f6-fa93-4eb1-b939-6544ba844214\",\"type\":\"Grid\"},{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"15f8cd81-4fec-4d05-bda0-78185a4dec89\",\"type\":\"CDSView\"},{\"attributes\":{\"data_source\":{\"id\":\"6ae154ab-2dd9-467f-9405-40a7f5607f59\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"cc91ab49-ad0c-4a60-b7f7-c028eb17209d\",\"type\":\"CDSView\"}},\"id\":\"0fecf8b7-44e7-4c31-8477-a249cc03473b\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null,\"data\":{}},\"id\":\"6ae154ab-2dd9-467f-9405-40a7f5607f59\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"interval\":12,\"num_minor_ticks\":0},\"id\":\"5f6573d6-a5db-4401-ad00-6081ab6e8455\",\"type\":\"SingleIntervalTicker\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"field\":\"MedalFill\"},\"line_color\":{\"field\":\"MedalLine\"},\"size\":{\"units\":\"screen\",\"value\":10},\"x\":{\"field\":\"MetersBack\"},\"y\":{\"field\":\"Year\"}},\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"9d22b06e-837e-4b77-8632-cbe152700241\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"0cc88575-d3f5-4132-bfb6-3bdf017e2359\",\"type\":\"CDSView\"},{\"attributes\":{\"interval\":5,\"num_minor_ticks\":0},\"id\":\"6b04205a-4efc-4e91-a629-f05cdeb0ffc9\",\"type\":\"SingleIntervalTicker\"},{\"attributes\":{},\"id\":\"d96edf1a-1d7a-4474-841a-f69b7268f13d\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"end\":0,\"start\":25.571428571428566},\"id\":\"1a69424c-3345-4e00-90fa-7197a7ce98e1\",\"type\":\"Range1d\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"15f8cd81-4fec-4d05-bda0-78185a4dec89\",\"type\":\"CDSView\"}},\"id\":\"7a6dfe4f-634e-4b6c-a3f5-bc4be0a7ecf6\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"text\":{\"field\":\"SelectedName\"},\"text_baseline\":\"middle\",\"text_font_size\":{\"value\":\"9pt\"},\"x\":{\"field\":\"MetersBack\"},\"x_offset\":{\"value\":10},\"y\":{\"field\":\"Year\"}},\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"0cc88575-d3f5-4132-bfb6-3bdf017e2359\",\"type\":\"CDSView\"}},\"id\":\"d8b62b87-35ab-4c2b-ad79-6fb9d98ff122\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"text\":{\"value\":\"No Olympics in 1940 or 1944\"},\"text_align\":\"center\",\"text_baseline\":\"middle\",\"text_color\":{\"value\":\"silver\"},\"text_font_size\":{\"value\":\"9pt\"},\"text_font_style\":\"italic\",\"x\":{\"value\":7.5},\"y\":{\"value\":1942}},\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_scroll\":\"auto\",\"active_tap\":\"auto\"},\"id\":\"cd21fab5-c0b2-48ad-9e67-234e9f11352b\",\"type\":\"Toolbar\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"MetersBack\",\"MedalLine\",\"SelectedName\",\"Name\",\"Country\",\"index\",\"Speed\",\"Medal\",\"Year\",\"MedalFill\",\"Time\",\"Abbrev\"],\"data\":{\"Abbrev\":[\"JAM\",\"JAM\",\"USA\",\"JAM\",\"TRI\",\"USA\",\"USA\",\"POR\",\"USA\",\"USA\",\"TRI\",\"BAR\",\"CAN\",\"NAM\",\"TRI\",\"GBR\",\"NAM\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"CAN\",\"GBR\",\"CUB\",\"BUL\",\"TRI\",\"JAM\",\"URS\",\"URS\",\"USA\",\"JAM\",\"USA\",\"JAM\",\"USA\",\"USA\",\"CUB\",\"CAN\",\"EUA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"AUS\",\"USA\",\"JAM\",\"GBR\",\"USA\",\"USA\",\"PAN\",\"USA\",\"USA\",\"NED\",\"USA\",\"USA\",\"GER\",\"CAN\",\"GBR\",\"GER\",\"GBR\",\"USA\",\"NZL\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"RSA\",\"USA\",\"CAN\",\"USA\",\"USA\",\"AUS\",\"USA\",\"USA\",\"USA\",\"USA\",\"USA\",\"AUS\",\"USA\",\"GER\",\"HUN\",\"USA\"],\"Country\":[\"Jamaica\",\"Jamaica\",\"United States\",\"Jamaica\",\"Trinidad and Tobago\",\"United States\",\"United States\",\"Portugal\",\"United States\",\"United States\",\"Trinidad and Tobago\",\"Barbados\",\"Canada\",\"Namibia\",\"Trinidad and Tobago\",\"Britain\",\"Namibia\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"Canada\",\"Britain\",\"Cuba\",\"Bulgaria\",\"Trinidad and Tobago\",\"Jamaica\",\"Soviet Union\",\"Soviet Union\",\"United States\",\"Jamaica\",\"United States\",\"Jamaica\",\"United States\",\"United States\",\"Cuba\",\"Canada\",\"United Team of Germany\",\"United States\",\"Britain\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Jamaica\",\"Britain\",\"United States\",\"United States\",\"Panama\",\"United States\",\"United States\",\"Netherlands\",\"United States\",\"United States\",\"Germany\",\"Canada\",\"Britain\",\"Germany\",\"Britain\",\"United States\",\"New Zealand\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"South Africa\",\"United States\",\"Canada\",\"United States\",\"United States\",\"Australia\",\"United States\",\"United States\",\"United States\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Germany\",\"Hungary\",\"United States\"],\"Medal\":[\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"bronze\"],\"MedalFill\":[\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#c59e8a\"],\"MedalLine\":[\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#98715d\"],\"MetersBack\":{\"__ndarray__\":\"AAAAAAAAAAD2OrETO7HzPzSH3n8tJvo/+LRJIXLQ4z+4oVs2BggFQE37LXJ6mgZApWIklDbeAUD2G7ItSKkCQBFzDHDwcwNAEXMMcPBzA0A7zUkgLtQMQMAp1V2sVRBA/rQrUbsSAUC4oVs2BggFQMdFF1100QVAuPaQy4qBCkC79onqQSMPQMAp1V2sVRBAV4wxxhhjB0A2Q3IHJ0gLQDvNSSAu1AxAO81JIC7UDEDqKu9YevsVQHzx4sWLFxdALDgfg/MxGEAsOB+D8zEYQO/PDHRHQh1AQ4IAOfAYEUCybdu2bdsRQGZfWb1LHhRAZl9ZvUseFED0/////9MXQEJPwDgDGxtAX4SfXIi6CUDAKdVdrFUQQFLnrrBHehFAiJmZmZmZDUBQWlpaWloWQFBaWlpaWhZAUFpaWlpaFkBQWlpaWloWQCQ5L4v4BBpAHkmSJEmSIEAeSZIkSZIgQN+t7HNITSJA1Imd2ImdHUDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQB5JkiRJkiBAJDkvi/gEGkAkOS+L+AQaQNSJndiJnR1AqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdA363sc0hNIkCoqqqqqqolQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDnoosuuugoQOeiiy666ChAiSRJkiQJLECa6xjFuY4tQJrrGMW5ji1A56KLLrroKECJJEmSJAksQIkkSZIkCSxA56KLLrroKEDBZ91ginwqQIkkSZIkCSxA/f////+/M0DYvE9xyRA1QCNJkiRJkjdAI0mSJEmSN0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Name\":[\"Usain Bolt\",\"Yohan Blake\",\"Justin Gatlin\",\"Usain Bolt\",\"Richard Thompson\",\"Walter Dix\",\"Justin Gatlin\",\"Francis Obikwelu\",\"Maurice Greene\",\"Maurice Greene\",\"Ato Boldon\",\"Obadele Thompson\",\"Donovan Bailey\",\"Frankie Fredericks\",\"Ato Boldon\",\"Linford Christie\",\"Frankie Fredericks\",\"Dennis Mitchell\",\"Carl Lewis\",\"Linford Christie\",\"Calvin Smith\",\"Carl Lewis\",\"Sam Graddy\",\"Ben Johnson\",\"Allan Wells\",\"Silvio Leonard Tartabull\",\"Petar Petrov\",\"Hasely Crawford\",\"Donald Quarrie\",\"Valery Borzov\",\"Valery Borzov\",\"Robert Taylor\",\"Lennox Miller\",\"Jim Hines\",\"Lennox Miller\",\"Charles Greene\",\"Bob Hayes\",\"Enrique Figuerola Camue\",\"Harry Jerome\",\"Armin Hary\",\"David Sime\",\"Peter Radford\",\"Bobby Joe Morrow\",\"W. Thane Baker\",\"Hector Hogan\",\"Lindy Remigino\",\"Herbert McKenley\",\"E. McDonald Bailey\",\"W. Harrison Dillard\",\"H. Norwood \\\"Barney\\\" Ewell\",\"Lloyd LaBeach\",\"Jesse Owens\",\"Ralph Metcalfe\",\"Martinus Osendarp\",\"T. \\\"Eddie\\\" Tolan\",\"Ralph Metcalfe\",\"Arthur Jonath\",\"Percy Williams\",\"John \\\"Jack\\\" London\",\"Georg Lammers\",\"Harold Abrahams\",\"Jackson Scholz\",\"Arthur Porritt\",\"Charles Paddock\",\"Morris Kirksey\",\"Harry Edward\",\"Ralph Craig\",\"Alvah Meyer\",\"Donald Lippincott\",\"Reginald Walker\",\"James Rector\",\"Robert Kerr\",\"Charles \\\"Archie\\\" Hahn\",\"Fay Moulton\",\"Nigel Barker\",\"Charles \\\"Archie\\\" Hahn\",\"Nathaniel Cartmell\",\"Bill Hogenson\",\"Frank Jarvis\",\"J. Walter Tewksbury\",\"Stanley Rowley\",\"Thomas Burke\",\"Fritz Hofmann\",\"Alojz Sokol\",\"Francis Lane\"],\"SelectedName\":[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Carl Lewis\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jim Hines\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jesse Owens\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Thomas Burke\",\"\",\"\",\"\"],\"Speed\":{\"__ndarray__\":\"D9dd9bfEJEA1SIM0SIMkQNPZ5YvTbSRAEB0COMyjJEBnpfVH8jgkQGugzZx/LiRAUs36M/hNJEDfP/mgskgkQPb3DMpvQyRA9vcMym9DJEBSQDMIIAUkQP8yCgKa6yNAUwg0hUBTJEBnpfVH8jgkQN7OkJi3MyRA9dmM748UJEB3uNvKx/UjQP8yCgKa6yNAKaWUUkopJEBoIvL9Zw8kQFJAMwggBSRAUkAzCCAFJEDuitWqiKAjQBw5cuTIkSNAg/MxOB+DI0CD8zE4H4MjQLW+ZrHQPyNAA1ahlXbhI0B2Xdd1XdcjQKh2L0ZPuSNAqHYvRk+5I0AAAAAAAIgjQBMU9wNwXCNAhZ9ciLoZJED/MgoCmusjQFfYI71o3CNAAAAAAAAAJECcm5ubm5sjQJybm5ubmyNAnJubm5ubI0Ccm5ubm5sjQAxNd7DfaiNAwzAMwzAMI0DDMAzDMAwjQO1zSE0w3iJAsRM7sRM7I0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQMMwDMMwDCNADE13sN9qI0AMTXew32ojQLETO7ETOyNATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJA7XNITTDeIkBMaC+hvYQiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkAvuuiiiy4iQC+66KKLLiJAt23btm3bIUCTLxs0+bIhQJMvGzT5siFAL7rooosuIkC3bdu2bdshQLdt27Zt2yFAL7rooosuIkBKIC7UnAQiQLdt27Zt2yFAq6qqqqqqIEAebd6nuGQgQPD7vu/7vh9A8Pu+7/u+H0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Time\":{\"__ndarray__\":\"w/UoXI9CI0AAAAAAAIAjQBSuR+F6lCNA4XoUrkdhI0BI4XoUrscjQFK4HoXr0SNAMzMzMzOzI0C4HoXrUbgjQD0K16NwvSNAPQrXo3C9I0B7FK5H4fojQBSuR+F6FCRArkfhehSuI0BI4XoUrscjQM3MzMzMzCNA7FG4HoXrI0AK16NwPQokQBSuR+F6FCRA16NwPQrXI0BxPQrXo/AjQHsUrkfh+iNAexSuR+H6I0DhehSuR2EkQHE9CtejcCRAAAAAAACAJEAAAAAAAIAkQEjhehSuxyRAH4XrUbgeJEApXI/C9SgkQEjhehSuRyRASOF6FK5HJEB7FK5H4XokQClcj8L1qCRAZmZmZmbmI0AUrkfhehQkQKRwPQrXIyRAAAAAAAAAJEBmZmZmZmYkQGZmZmZmZiRAZmZmZmZmJEBmZmZmZmYkQJqZmZmZmSRAAAAAAAAAJUAAAAAAAAAlQDMzMzMzMyVAzczMzMzMJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQAAAAAAAACVAmpmZmZmZJECamZmZmZkkQM3MzMzMzCRAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAMzMzMzMzJUCamZmZmZklQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUAAAAAAAAAmQAAAAAAAACZAZmZmZmZmJkCamZmZmZkmQJqZmZmZmSZAAAAAAAAAJkBmZmZmZmYmQGZmZmZmZiZAAAAAAAAAJkAzMzMzMzMmQGZmZmZmZiZAAAAAAAAAKEBmZmZmZmYoQDMzMzMzMylAMzMzMzMzKUA=\",\"dtype\":\"float64\",\"shape\":[85]},\"Year\":[2012,2012,2012,2008,2008,2008,2004,2004,2004,2000,2000,2000,1996,1996,1996,1992,1992,1992,1988,1988,1988,1984,1984,1984,1980,1980,1980,1976,1976,1976,1972,1972,1972,1968,1968,1968,1964,1964,1964,1960,1960,1960,1956,1956,1956,1952,1952,1952,1948,1948,1948,1936,1936,1936,1932,1932,1932,1928,1928,1928,1924,1924,1924,1920,1920,1920,1912,1912,1912,1908,1908,1908,1906,1906,1906,1904,1904,1904,1900,1900,1900,1896,1896,1896,1896],\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84]}},\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"formatter\":{\"id\":\"7c26425d-c20f-4ead-baec-ec9df359f075\",\"type\":\"BasicTickFormatter\"},\"major_tick_in\":-5,\"major_tick_out\":10,\"plot\":{\"id\":\"75f2e525-e634-424c-a4f5-17743e75dff9\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"5f6573d6-a5db-4401-ad00-6081ab6e8455\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"c09e0c50-d57d-4b66-a6e5-f83d7cd58aba\",\"type\":\"LinearAxis\"}],\"root_ids\":[\"75f2e525-e634-424c-a4f5-17743e75dff9\"]},\"title\":\"Bokeh Application\",\"version\":\"0.12.13\"}};\n",
       "  var render_items = [{\"docid\":\"e45d1607-b9e0-4629-835b-d77cac56faa2\",\"elementid\":\"61aebced-e287-4016-8297-ec274527af38\",\"modelid\":\"75f2e525-e634-424c-a4f5-17743e75dff9\"}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "75f2e525-e634-424c-a4f5-17743e75dff9"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show(plot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 添加一个悬停工具\n",
    "\n",
    "最后，我们添加一个悬停工具来显示我们在列数据源中另外添加的列数据。为了对外观样式进行更多的控制，我们使用模板语法来设置工具提示。工具可以使用 `plot.add_tools` 方法添加。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.models import HoverTool"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "tooltips = \"\"\"\n",
    "<div>\n",
    "    <span style=\"font-size: 15px;\">@Name</span>&nbsp;\n",
    "    <span style=\"font-size: 10px; color: #666;\">(@Abbrev)</span>\n",
    "</div>\n",
    "<div>\n",
    "    <span style=\"font-size: 17px; font-weight: bold;\">@Time{0.00}</span>&nbsp;\n",
    "    <span style=\"font-size: 10px; color: #666;\">@Year</span>\n",
    "</div>\n",
    "<div style=\"font-size: 11px; color: #666;\">@{MetersBack}{0.00} meters behind</div>\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "xdr = Range1d(start=sprint.MetersBack.max()+2, end=0)  # +2 is for padding\n",
    "ydr = DataRange1d(range_padding=0.05)  \n",
    "\n",
    "plot = Plot(x_range=xdr, y_range=ydr, **plot_options)\n",
    "plot.title.text = \"Usain Bolt vs. 116 years of Olympic sprinters\"\n",
    "medal = plot.add_glyph(source, medal_glyph)  # we need this renderer to configure the hover tool\n",
    "plot.add_glyph(source, athlete_glyph)\n",
    "plot.add_glyph(no_olympics_glyph)\n",
    "\n",
    "xticker = SingleIntervalTicker(interval=5, num_minor_ticks=0)\n",
    "xaxis = LinearAxis(ticker=xticker, axis_line_color=None, major_tick_line_color=None,\n",
    "                   axis_label=\"Meters behind 2012 Bolt\", axis_label_text_font_size=\"10pt\", \n",
    "                   axis_label_text_font_style=\"bold\")\n",
    "plot.add_layout(xaxis, \"below\")\n",
    "\n",
    "xgrid = Grid(dimension=0, ticker=xaxis.ticker, grid_line_dash=\"dashed\")\n",
    "plot.add_layout(xgrid)\n",
    "\n",
    "yticker = SingleIntervalTicker(interval=12, num_minor_ticks=0)\n",
    "yaxis = LinearAxis(ticker=yticker, major_tick_in=-5, major_tick_out=10)\n",
    "plot.add_layout(yaxis, \"right\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "hover = HoverTool(tooltips=tooltips, renderers=[medal])\n",
    "plot.add_tools(hover)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div class=\"bk-root\">\n",
       "    <div class=\"bk-plotdiv\" id=\"0ff38859-0f0c-40cd-858b-746cf6f28378\"></div>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"59c3e40d-4806-4147-853f-0be4cd704098\":{\"roots\":{\"references\":[{\"attributes\":{},\"id\":\"272bae21-b2ec-4765-b47e-360a2e3076d0\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"below\":[{\"id\":\"be763b01-233c-4bfd-8586-c2a438f9028f\",\"type\":\"LinearAxis\"}],\"outline_line_color\":{\"value\":null},\"plot_height\":480,\"plot_width\":800,\"renderers\":[{\"id\":\"e15643d0-fbab-4ca5-8b7a-6565d253b465\",\"type\":\"GlyphRenderer\"},{\"id\":\"9fb98483-517f-4294-854c-b01e245d39f7\",\"type\":\"GlyphRenderer\"},{\"id\":\"ed62c074-6cbd-4b2c-8d69-d9dc95edd428\",\"type\":\"GlyphRenderer\"},{\"id\":\"be763b01-233c-4bfd-8586-c2a438f9028f\",\"type\":\"LinearAxis\"},{\"id\":\"cedd77e3-35a6-4e45-be7f-a414f169c246\",\"type\":\"Grid\"},{\"id\":\"d04754d5-17e5-4985-9afc-0e6d96898694\",\"type\":\"LinearAxis\"}],\"right\":[{\"id\":\"d04754d5-17e5-4985-9afc-0e6d96898694\",\"type\":\"LinearAxis\"}],\"title\":{\"id\":\"616abe73-bf82-4ba8-bbf2-60f030bf06be\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"5df3c44c-95a8-4966-bd0d-530926ec4853\",\"type\":\"Toolbar\"},\"toolbar_location\":null,\"x_range\":{\"id\":\"8592c67b-2a47-4b88-a688-34b074a53fd4\",\"type\":\"Range1d\"},\"x_scale\":{\"id\":\"fad287b0-24b3-4283-9cb3-93c2ef2cedd4\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"243a82e1-4dfd-4006-879f-0b27f8b3f43d\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"2483a6e9-7b57-4922-b4f6-904f26dd1f49\",\"type\":\"LinearScale\"}},\"id\":\"03d8432f-1b83-4a9b-b96f-00975c6047a7\",\"type\":\"Plot\"},{\"attributes\":{\"axis_label\":\"Meters behind 2012 Bolt\",\"axis_label_text_font_size\":{\"value\":\"10pt\"},\"axis_label_text_font_style\":\"bold\",\"axis_line_color\":{\"value\":null},\"formatter\":{\"id\":\"1987ec0a-929a-4e24-b19e-4137d4b15a11\",\"type\":\"BasicTickFormatter\"},\"major_tick_line_color\":{\"value\":null},\"plot\":{\"id\":\"03d8432f-1b83-4a9b-b96f-00975c6047a7\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"ad2b78d0-2ead-46a2-9b7e-d6dc6e43da36\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"be763b01-233c-4bfd-8586-c2a438f9028f\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1987ec0a-929a-4e24-b19e-4137d4b15a11\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"callback\":null,\"range_padding\":0.05},\"id\":\"243a82e1-4dfd-4006-879f-0b27f8b3f43d\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null,\"renderers\":[{\"id\":\"e15643d0-fbab-4ca5-8b7a-6565d253b465\",\"type\":\"GlyphRenderer\"}],\"tooltips\":\"\\n<div>\\n    <span style=\\\"font-size: 15px;\\\">@Name</span>&nbsp;\\n    <span style=\\\"font-size: 10px; color: #666;\\\">(@Abbrev)</span>\\n</div>\\n<div>\\n    <span style=\\\"font-size: 17px; font-weight: bold;\\\">@Time{0.00}</span>&nbsp;\\n    <span style=\\\"font-size: 10px; color: #666;\\\">@Year</span>\\n</div>\\n<div style=\\\"font-size: 11px; color: #666;\\\">@{MetersBack}{0.00} meters behind</div>\\n\"},\"id\":\"52559b82-2c0a-4bf5-8fa9-425e005d5cab\",\"type\":\"HoverTool\"},{\"attributes\":{\"interval\":5,\"num_minor_ticks\":0},\"id\":\"ad2b78d0-2ead-46a2-9b7e-d6dc6e43da36\",\"type\":\"SingleIntervalTicker\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"52559b82-2c0a-4bf5-8fa9-425e005d5cab\",\"type\":\"HoverTool\"}]},\"id\":\"5df3c44c-95a8-4966-bd0d-530926ec4853\",\"type\":\"Toolbar\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"72fb866e-8210-4bf1-9cb8-5eb75012ca49\",\"type\":\"CDSView\"}},\"id\":\"9fb98483-517f-4294-854c-b01e245d39f7\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"fad287b0-24b3-4283-9cb3-93c2ef2cedd4\",\"type\":\"LinearScale\"},{\"attributes\":{\"callback\":null,\"end\":0,\"start\":25.571428571428566},\"id\":\"8592c67b-2a47-4b88-a688-34b074a53fd4\",\"type\":\"Range1d\"},{\"attributes\":{},\"id\":\"2483a6e9-7b57-4922-b4f6-904f26dd1f49\",\"type\":\"LinearScale\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"field\":\"MedalFill\"},\"line_color\":{\"field\":\"MedalLine\"},\"size\":{\"units\":\"screen\",\"value\":10},\"x\":{\"field\":\"MetersBack\"},\"y\":{\"field\":\"Year\"}},\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},{\"attributes\":{\"callback\":null,\"data\":{}},\"id\":\"be29869a-38c1-4d93-ab52-1ca0e6aec3eb\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"data_source\":{\"id\":\"be29869a-38c1-4d93-ab52-1ca0e6aec3eb\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"f9e7b3e5-4395-4f88-b02d-65b81e7d4d2e\",\"type\":\"CDSView\"}},\"id\":\"ed62c074-6cbd-4b2c-8d69-d9dc95edd428\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"text\":{\"value\":\"No Olympics in 1940 or 1944\"},\"text_align\":\"center\",\"text_baseline\":\"middle\",\"text_color\":{\"value\":\"silver\"},\"text_font_size\":{\"value\":\"9pt\"},\"text_font_style\":\"italic\",\"x\":{\"value\":7.5},\"y\":{\"value\":1942}},\"id\":\"6547a6bb-c1e4-4278-b2c3-c0e2228a0d97\",\"type\":\"Text\"},{\"attributes\":{\"formatter\":{\"id\":\"272bae21-b2ec-4765-b47e-360a2e3076d0\",\"type\":\"BasicTickFormatter\"},\"major_tick_in\":-5,\"major_tick_out\":10,\"plot\":{\"id\":\"03d8432f-1b83-4a9b-b96f-00975c6047a7\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1a5123f1-dfec-4ba5-94df-045db96d88c6\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"d04754d5-17e5-4985-9afc-0e6d96898694\",\"type\":\"LinearAxis\"},{\"attributes\":{\"interval\":12,\"num_minor_ticks\":0},\"id\":\"1a5123f1-dfec-4ba5-94df-045db96d88c6\",\"type\":\"SingleIntervalTicker\"},{\"attributes\":{\"data_source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"ffa34717-aa65-4113-aa9b-c268b066d56e\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"view\":{\"id\":\"0969ca72-8d64-4fa5-b3e6-993e4624b485\",\"type\":\"CDSView\"}},\"id\":\"e15643d0-fbab-4ca5-8b7a-6565d253b465\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"72fb866e-8210-4bf1-9cb8-5eb75012ca49\",\"type\":\"CDSView\"},{\"attributes\":{\"text\":{\"field\":\"SelectedName\"},\"text_baseline\":\"middle\",\"text_font_size\":{\"value\":\"9pt\"},\"x\":{\"field\":\"MetersBack\"},\"x_offset\":{\"value\":10},\"y\":{\"field\":\"Year\"}},\"id\":\"5f8bb15e-a21c-40eb-869a-680dde5ef6c3\",\"type\":\"Text\"},{\"attributes\":{\"source\":{\"id\":\"be29869a-38c1-4d93-ab52-1ca0e6aec3eb\",\"type\":\"ColumnDataSource\"}},\"id\":\"f9e7b3e5-4395-4f88-b02d-65b81e7d4d2e\",\"type\":\"CDSView\"},{\"attributes\":{\"grid_line_dash\":[6],\"plot\":{\"id\":\"03d8432f-1b83-4a9b-b96f-00975c6047a7\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"ad2b78d0-2ead-46a2-9b7e-d6dc6e43da36\",\"type\":\"SingleIntervalTicker\"}},\"id\":\"cedd77e3-35a6-4e45-be7f-a414f169c246\",\"type\":\"Grid\"},{\"attributes\":{\"plot\":null,\"text\":\"Usain Bolt vs. 116 years of Olympic sprinters\"},\"id\":\"616abe73-bf82-4ba8-bbf2-60f030bf06be\",\"type\":\"Title\"},{\"attributes\":{\"source\":{\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}},\"id\":\"0969ca72-8d64-4fa5-b3e6-993e4624b485\",\"type\":\"CDSView\"},{\"attributes\":{\"callback\":null,\"column_names\":[\"MetersBack\",\"MedalLine\",\"SelectedName\",\"Name\",\"Country\",\"index\",\"Speed\",\"Medal\",\"Year\",\"MedalFill\",\"Time\",\"Abbrev\"],\"data\":{\"Abbrev\":[\"JAM\",\"JAM\",\"USA\",\"JAM\",\"TRI\",\"USA\",\"USA\",\"POR\",\"USA\",\"USA\",\"TRI\",\"BAR\",\"CAN\",\"NAM\",\"TRI\",\"GBR\",\"NAM\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"CAN\",\"GBR\",\"CUB\",\"BUL\",\"TRI\",\"JAM\",\"URS\",\"URS\",\"USA\",\"JAM\",\"USA\",\"JAM\",\"USA\",\"USA\",\"CUB\",\"CAN\",\"EUA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"AUS\",\"USA\",\"JAM\",\"GBR\",\"USA\",\"USA\",\"PAN\",\"USA\",\"USA\",\"NED\",\"USA\",\"USA\",\"GER\",\"CAN\",\"GBR\",\"GER\",\"GBR\",\"USA\",\"NZL\",\"USA\",\"USA\",\"GBR\",\"USA\",\"USA\",\"USA\",\"RSA\",\"USA\",\"CAN\",\"USA\",\"USA\",\"AUS\",\"USA\",\"USA\",\"USA\",\"USA\",\"USA\",\"AUS\",\"USA\",\"GER\",\"HUN\",\"USA\"],\"Country\":[\"Jamaica\",\"Jamaica\",\"United States\",\"Jamaica\",\"Trinidad and Tobago\",\"United States\",\"United States\",\"Portugal\",\"United States\",\"United States\",\"Trinidad and Tobago\",\"Barbados\",\"Canada\",\"Namibia\",\"Trinidad and Tobago\",\"Britain\",\"Namibia\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"Canada\",\"Britain\",\"Cuba\",\"Bulgaria\",\"Trinidad and Tobago\",\"Jamaica\",\"Soviet Union\",\"Soviet Union\",\"United States\",\"Jamaica\",\"United States\",\"Jamaica\",\"United States\",\"United States\",\"Cuba\",\"Canada\",\"United Team of Germany\",\"United States\",\"Britain\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Jamaica\",\"Britain\",\"United States\",\"United States\",\"Panama\",\"United States\",\"United States\",\"Netherlands\",\"United States\",\"United States\",\"Germany\",\"Canada\",\"Britain\",\"Germany\",\"Britain\",\"United States\",\"New Zealand\",\"United States\",\"United States\",\"Britain\",\"United States\",\"United States\",\"United States\",\"South Africa\",\"United States\",\"Canada\",\"United States\",\"United States\",\"Australia\",\"United States\",\"United States\",\"United States\",\"United States\",\"United States\",\"Australia\",\"United States\",\"Germany\",\"Hungary\",\"United States\"],\"Medal\":[\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"gold\",\"silver\",\"bronze\",\"bronze\"],\"MedalFill\":[\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#efcf6d\",\"#cccccc\",\"#c59e8a\",\"#c59e8a\"],\"MedalLine\":[\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#c8a850\",\"#b0b0b1\",\"#98715d\",\"#98715d\"],\"MetersBack\":{\"__ndarray__\":\"AAAAAAAAAAD2OrETO7HzPzSH3n8tJvo/+LRJIXLQ4z+4oVs2BggFQE37LXJ6mgZApWIklDbeAUD2G7ItSKkCQBFzDHDwcwNAEXMMcPBzA0A7zUkgLtQMQMAp1V2sVRBA/rQrUbsSAUC4oVs2BggFQMdFF1100QVAuPaQy4qBCkC79onqQSMPQMAp1V2sVRBAV4wxxhhjB0A2Q3IHJ0gLQDvNSSAu1AxAO81JIC7UDEDqKu9YevsVQHzx4sWLFxdALDgfg/MxGEAsOB+D8zEYQO/PDHRHQh1AQ4IAOfAYEUCybdu2bdsRQGZfWb1LHhRAZl9ZvUseFED0/////9MXQEJPwDgDGxtAX4SfXIi6CUDAKdVdrFUQQFLnrrBHehFAiJmZmZmZDUBQWlpaWloWQFBaWlpaWhZAUFpaWlpaFkBQWlpaWloWQCQ5L4v4BBpAHkmSJEmSIEAeSZIkSZIgQN+t7HNITSJA1Imd2ImdHUDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQNSJndiJnR1AJDkvi/gEGkDUiZ3YiZ0dQB5JkiRJkiBAJDkvi/gEGkAkOS+L+AQaQNSJndiJnR1AqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdA363sc0hNIkCoqqqqqqolQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDUtJ8sgU0nQNS0nyyBTSdAqKqqqqqqJUDnoosuuugoQOeiiy666ChAiSRJkiQJLECa6xjFuY4tQJrrGMW5ji1A56KLLrroKECJJEmSJAksQIkkSZIkCSxA56KLLrroKEDBZ91ginwqQIkkSZIkCSxA/f////+/M0DYvE9xyRA1QCNJkiRJkjdAI0mSJEmSN0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Name\":[\"Usain Bolt\",\"Yohan Blake\",\"Justin Gatlin\",\"Usain Bolt\",\"Richard Thompson\",\"Walter Dix\",\"Justin Gatlin\",\"Francis Obikwelu\",\"Maurice Greene\",\"Maurice Greene\",\"Ato Boldon\",\"Obadele Thompson\",\"Donovan Bailey\",\"Frankie Fredericks\",\"Ato Boldon\",\"Linford Christie\",\"Frankie Fredericks\",\"Dennis Mitchell\",\"Carl Lewis\",\"Linford Christie\",\"Calvin Smith\",\"Carl Lewis\",\"Sam Graddy\",\"Ben Johnson\",\"Allan Wells\",\"Silvio Leonard Tartabull\",\"Petar Petrov\",\"Hasely Crawford\",\"Donald Quarrie\",\"Valery Borzov\",\"Valery Borzov\",\"Robert Taylor\",\"Lennox Miller\",\"Jim Hines\",\"Lennox Miller\",\"Charles Greene\",\"Bob Hayes\",\"Enrique Figuerola Camue\",\"Harry Jerome\",\"Armin Hary\",\"David Sime\",\"Peter Radford\",\"Bobby Joe Morrow\",\"W. Thane Baker\",\"Hector Hogan\",\"Lindy Remigino\",\"Herbert McKenley\",\"E. McDonald Bailey\",\"W. Harrison Dillard\",\"H. Norwood \\\"Barney\\\" Ewell\",\"Lloyd LaBeach\",\"Jesse Owens\",\"Ralph Metcalfe\",\"Martinus Osendarp\",\"T. \\\"Eddie\\\" Tolan\",\"Ralph Metcalfe\",\"Arthur Jonath\",\"Percy Williams\",\"John \\\"Jack\\\" London\",\"Georg Lammers\",\"Harold Abrahams\",\"Jackson Scholz\",\"Arthur Porritt\",\"Charles Paddock\",\"Morris Kirksey\",\"Harry Edward\",\"Ralph Craig\",\"Alvah Meyer\",\"Donald Lippincott\",\"Reginald Walker\",\"James Rector\",\"Robert Kerr\",\"Charles \\\"Archie\\\" Hahn\",\"Fay Moulton\",\"Nigel Barker\",\"Charles \\\"Archie\\\" Hahn\",\"Nathaniel Cartmell\",\"Bill Hogenson\",\"Frank Jarvis\",\"J. Walter Tewksbury\",\"Stanley Rowley\",\"Thomas Burke\",\"Fritz Hofmann\",\"Alojz Sokol\",\"Francis Lane\"],\"SelectedName\":[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Carl Lewis\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jim Hines\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Jesse Owens\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"Thomas Burke\",\"\",\"\",\"\"],\"Speed\":{\"__ndarray__\":\"D9dd9bfEJEA1SIM0SIMkQNPZ5YvTbSRAEB0COMyjJEBnpfVH8jgkQGugzZx/LiRAUs36M/hNJEDfP/mgskgkQPb3DMpvQyRA9vcMym9DJEBSQDMIIAUkQP8yCgKa6yNAUwg0hUBTJEBnpfVH8jgkQN7OkJi3MyRA9dmM748UJEB3uNvKx/UjQP8yCgKa6yNAKaWUUkopJEBoIvL9Zw8kQFJAMwggBSRAUkAzCCAFJEDuitWqiKAjQBw5cuTIkSNAg/MxOB+DI0CD8zE4H4MjQLW+ZrHQPyNAA1ahlXbhI0B2Xdd1XdcjQKh2L0ZPuSNAqHYvRk+5I0AAAAAAAIgjQBMU9wNwXCNAhZ9ciLoZJED/MgoCmusjQFfYI71o3CNAAAAAAAAAJECcm5ubm5sjQJybm5ubmyNAnJubm5ubI0Ccm5ubm5sjQAxNd7DfaiNAwzAMwzAMI0DDMAzDMAwjQO1zSE0w3iJAsRM7sRM7I0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQLETO7ETOyNADE13sN9qI0CxEzuxEzsjQMMwDMMwDCNADE13sN9qI0AMTXew32ojQLETO7ETOyNATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJA7XNITTDeIkBMaC+hvYQiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkCUJbBpP1kiQJQlsGk/WSJATGgvob2EIkAvuuiiiy4iQC+66KKLLiJAt23btm3bIUCTLxs0+bIhQJMvGzT5siFAL7rooosuIkC3bdu2bdshQLdt27Zt2yFAL7rooosuIkBKIC7UnAQiQLdt27Zt2yFAq6qqqqqqIEAebd6nuGQgQPD7vu/7vh9A8Pu+7/u+H0A=\",\"dtype\":\"float64\",\"shape\":[85]},\"Time\":{\"__ndarray__\":\"w/UoXI9CI0AAAAAAAIAjQBSuR+F6lCNA4XoUrkdhI0BI4XoUrscjQFK4HoXr0SNAMzMzMzOzI0C4HoXrUbgjQD0K16NwvSNAPQrXo3C9I0B7FK5H4fojQBSuR+F6FCRArkfhehSuI0BI4XoUrscjQM3MzMzMzCNA7FG4HoXrI0AK16NwPQokQBSuR+F6FCRA16NwPQrXI0BxPQrXo/AjQHsUrkfh+iNAexSuR+H6I0DhehSuR2EkQHE9CtejcCRAAAAAAACAJEAAAAAAAIAkQEjhehSuxyRAH4XrUbgeJEApXI/C9SgkQEjhehSuRyRASOF6FK5HJEB7FK5H4XokQClcj8L1qCRAZmZmZmbmI0AUrkfhehQkQKRwPQrXIyRAAAAAAAAAJEBmZmZmZmYkQGZmZmZmZiRAZmZmZmZmJEBmZmZmZmYkQJqZmZmZmSRAAAAAAAAAJUAAAAAAAAAlQDMzMzMzMyVAzczMzMzMJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQM3MzMzMzCRAmpmZmZmZJEDNzMzMzMwkQAAAAAAAACVAmpmZmZmZJECamZmZmZkkQM3MzMzMzCRAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAMzMzMzMzJUCamZmZmZklQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUDNzMzMzMwlQM3MzMzMzCVAmpmZmZmZJUAAAAAAAAAmQAAAAAAAACZAZmZmZmZmJkCamZmZmZkmQJqZmZmZmSZAAAAAAAAAJkBmZmZmZmYmQGZmZmZmZiZAAAAAAAAAJkAzMzMzMzMmQGZmZmZmZiZAAAAAAAAAKEBmZmZmZmYoQDMzMzMzMylAMzMzMzMzKUA=\",\"dtype\":\"float64\",\"shape\":[85]},\"Year\":[2012,2012,2012,2008,2008,2008,2004,2004,2004,2000,2000,2000,1996,1996,1996,1992,1992,1992,1988,1988,1988,1984,1984,1984,1980,1980,1980,1976,1976,1976,1972,1972,1972,1968,1968,1968,1964,1964,1964,1960,1960,1960,1956,1956,1956,1952,1952,1952,1948,1948,1948,1936,1936,1936,1932,1932,1932,1928,1928,1928,1924,1924,1924,1920,1920,1920,1912,1912,1912,1908,1908,1908,1906,1906,1906,1904,1904,1904,1900,1900,1900,1896,1896,1896,1896],\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84]}},\"id\":\"81bf3283-e25a-4fe5-b3b2-0f89023828d4\",\"type\":\"ColumnDataSource\"}],\"root_ids\":[\"03d8432f-1b83-4a9b-b96f-00975c6047a7\"]},\"title\":\"Bokeh Application\",\"version\":\"0.12.13\"}};\n",
       "  var render_items = [{\"docid\":\"59c3e40d-4806-4147-853f-0be4cd704098\",\"elementid\":\"0ff38859-0f0c-40cd-858b-746cf6f28378\",\"modelid\":\"03d8432f-1b83-4a9b-b96f-00975c6047a7\"}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\")\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "03d8432f-1b83-4a9b-b96f-00975c6047a7"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show(plot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 作业"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 定制用户模型\n",
    "\n",
    "使用用户自定义模型来扩充Bokeh内置模型库是可行的。某些情况下，该功能是很有价值的用：\n",
    "* 自定义现有的Bokeh模型的行为\n",
    "* 包装和连接其他JS库到Bokeh\n",
    "\n",
    "有了这项功能，在无需建立一个完整的Bokeh发展环境的情况下，高级用户可以轻松地尝试新的功能或技术。\n",
    "\n",
    "本节给出了一个用JavaScript实现自定义模型的基本轮廓，继承一个现有的BokehJS模型。详情请参考用户手册中 [扩展 Bokeh](http://bokeh.pydata.org/en/latest/docs/user_guide/extensions.html) 章节。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实现 JavaScript 模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "JS_CODE = \"\"\"\n",
    "import {div, empty} from \"core/dom\"\n",
    "\n",
    "# The \"core/properties\" module has all the property types\n",
    "import * as p from \"core/properties\"\n",
    "\n",
    "# We will subclass in JavaScript from the same class that was subclassed\n",
    "# from in Python\n",
    "import {LayoutDOM, LayoutDOMView} from \"models/layouts/layout_dom\"\n",
    "\n",
    "# This model will actually need to render things, so we must provide\n",
    "# view. The LayoutDOM model has a view already, so we will start with that\n",
    "export class CustomView extends LayoutDOMView\n",
    "\n",
    "  initialize: (options) ->\n",
    "    super(options)\n",
    "\n",
    "    @render()\n",
    "\n",
    "    # Set Backbone listener so that when the Bokeh slider has a change\n",
    "    # event, we can process the new data\n",
    "    @connect(@model.slider.change, () => @render())\n",
    "\n",
    "  render: () ->\n",
    "    # Backbone Views create <div> elements by default, accessible as @el.\n",
    "    # Many Bokeh views ignore this default <div>, and instead do things\n",
    "    # like draw to the HTML canvas. In this case though, we change the\n",
    "    # contents of the <div>, based on the current slider value.\n",
    "    empty(@el)\n",
    "    @el.appendChild(div({\n",
    "      style: {\n",
    "        color: '#686d8e'\n",
    "        'background-color': '#2a3153'\n",
    "      }\n",
    "    }, \"#{@model.text}: #{@model.slider.value}\"))\n",
    "\n",
    "export class Custom extends LayoutDOM\n",
    "\n",
    "  # If there is an associated view, this is boilerplate.\n",
    "  default_view: CustomView\n",
    "\n",
    "  # The ``type`` class attribute should generally match exactly the name\n",
    "  # of the corresponding Python class.\n",
    "  type: \"Custom\"\n",
    "\n",
    "  # The @define block adds corresponding \"properties\" to the JS model. These\n",
    "  # should basically line up 1-1 with the Python model class. Most property\n",
    "  # types have counterparts, e.g. bokeh.core.properties.String will be\n",
    "  # p.String in the JS implementation. Where the JS type system is not yet\n",
    "  # as rich, you can use p.Any as a \"wildcard\" property type.\n",
    "  @define {\n",
    "    text:   [ p.String ]\n",
    "    slider: [ p.Any    ]\n",
    "  }\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义 Python 模型\n",
    "\n",
    "把 JavaScript 实现附加到对应的 Python Bokeh 模型："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bokeh.core.properties import String, Instance\n",
    "from bokeh.models import LayoutDOM, Slider\n",
    "\n",
    "class Custom(LayoutDOM):\n",
    "\n",
    "    __implementation__ = JS_CODE\n",
    "\n",
    "    text = String(default=\"Custom text\")\n",
    "\n",
    "    slider = Instance(Slider)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用 Python 模型\n",
    "\n",
    "然后，新定义的模型就可以像内置的Bokeh模型一样使用了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "from bokeh.io import show\n",
    "from bokeh.layouts import column\n",
    "from bokeh.models import Slider\n",
    "\n",
    "slider = Slider(start=0, end=10, step=0.1, value=0, title=\"value\")\n",
    "\n",
    "custom = Custom(text=\"Special Slider Display\", slider=slider)\n",
    "\n",
    "layout = column(slider, custom)\n",
    "\n",
    "# Currently a bug preventing custom extensions working in notebooks\n",
    "#show(layout)"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
